home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 May: Tool Chest / Developer CD Series May 1996 (Tool Chest) (Apple Computer) (1996).iso / Tool Chest / Development Tools & Languages / • Other Platforms / PCCTS 1.31 / h / AParser.C < prev    next >
Encoding:
C/C++ Source or Header  |  1995-03-10  |  12.2 KB  |  504 lines  |  [TEXT/MPS ]

  1. /* ANTLRParser.C
  2.  *
  3.  * SOFTWARE RIGHTS
  4.  *
  5.  * We reserve no LEGAL rights to the Purdue Compiler Construction Tool
  6.  * Set (PCCTS) -- PCCTS is in the public domain.  An individual or
  7.  * company may do whatever they wish with source code distributed with
  8.  * PCCTS or the code generated by PCCTS, including the incorporation of
  9.  * PCCTS, or its output, into commerical software.
  10.  * 
  11.  * We encourage users to develop software with PCCTS.  However, we do ask
  12.  * that credit is given to us for developing PCCTS.  By "credit",
  13.  * we mean that if you incorporate our source code into one of your
  14.  * programs (commercial product, research project, or otherwise) that you
  15.  * acknowledge this fact somewhere in the documentation, research report,
  16.  * etc...  If you like PCCTS and have developed a nice tool with the
  17.  * output, please mention that you developed it using PCCTS.  In
  18.  * addition, we ask that this header remain intact in our source code.
  19.  * As long as these guidelines are kept, we expect to continue enhancing
  20.  * this system and expect to make other tools available as they are
  21.  * completed.
  22.  *
  23.  * ANTLR 1.31
  24.  * Terence Parr
  25.  * Parr Research Corporation
  26.  * with Purdue University and AHPCRC, University of Minnesota
  27.  * 1989-1995
  28.  */
  29. #include <stdlib.h>
  30. #include <stdarg.h>
  31. #include <string.h>
  32. #include <stdio.h>
  33.  
  34. /* I have to put this here due to C++ limitation
  35.  * that you can't have a 'forward' decl for enums.
  36.  * I hate C++!!!!!!!!!!!!!!!
  37.  */
  38. enum TokenType { TER_HATES_CPP, ITS_UTTER_GARBAGE, WITH_SOME_GOOD_IDEAS };
  39.  
  40. #include "config.h"
  41. #include ATOKEN_H
  42. #include ATOKENBUFFER_H
  43. #include APARSER_H
  44.  
  45. static const zzINF_DEF_TOKEN_BUFFER_SIZE = 2000;
  46. static const zzINF_BUFFER_TOKEN_CHUNK_SIZE = 1000;
  47.  
  48.                  /* L o o k a h e a d  M a c r o s */
  49.  
  50. /* maximum of 32 bits/unsigned int and must be 8 bits/byte;
  51.  * we only use 8 bits of it.
  52.  */
  53. SetWordType ANTLRParser::bitmask[sizeof(SetWordType)*8] = {
  54.     0x00000001, 0x00000002, 0x00000004, 0x00000008,
  55.     0x00000010, 0x00000020, 0x00000040, 0x00000080
  56. };
  57.  
  58. char ANTLRParser::eMsgBuffer[500] = "";
  59.  
  60. ANTLRParser::
  61. ~ANTLRParser()
  62. {
  63.     delete [] token_type;
  64. }
  65.  
  66. ANTLRParser::
  67. ANTLRParser(ANTLRTokenBuffer *inputTokens,
  68.             int k,
  69.             int use_inf_look,
  70.             int dlook,
  71.             int ssize)
  72. {
  73.     LLk = k;
  74.     can_use_inf_look = use_inf_look;
  75.     demand_look = dlook;
  76.     bsetsize = ssize;
  77.  
  78.     guessing = 0;
  79.     token_tbl = NULL;
  80.     eofToken = (TokenType)1;
  81.  
  82.     // allocate lookahead buffer
  83.     token_type = new TokenType[LLk];
  84.     lap = 0;
  85.     labase = 0;
  86.     dirty = 0;
  87.  
  88.     /* prime lookahead buffer, point to inputTokens */
  89.     this->inputTokens = inputTokens;
  90.     this->inputTokens->setMinTokens(k);
  91. }
  92.  
  93. void ANTLRParser::init()
  94. {
  95.    prime_lookahead();
  96. }
  97.  
  98. int ANTLRParser::
  99. guess(ANTLRParserState *st)
  100. {
  101.     saveState(st);
  102.     guessing = 1;
  103.     return setjmp(guess_start.state);
  104. }
  105.  
  106. void ANTLRParser::
  107. saveState(ANTLRParserState *buf)
  108. {
  109.     buf->guess_start = guess_start;
  110.     buf->guessing = guessing;
  111.     buf->inf_labase = inf_labase;
  112.     buf->inf_last = inf_last;
  113.     buf->dirty = dirty;
  114. }
  115.  
  116. void ANTLRParser::
  117. restoreState(ANTLRParserState *buf)
  118. {
  119.     int i;
  120.  
  121.     guess_start = buf->guess_start;
  122.     guessing = buf->guessing;
  123.     inf_labase = buf->inf_labase;
  124.     inf_last = buf->inf_last;
  125.     dirty = buf->dirty;
  126.  
  127.     // restore lookahead buffer from k tokens before restored TokenBuffer position
  128.     // if demand_look, then I guess we don't look backwards for these tokens.
  129.     for (i=1; i<=LLk; i++) token_type[i-1] =
  130.         ((ANTLRTokenBase *)inputTokens->bufferedToken(i-LLk))->getType();
  131.     lap = 0;
  132.     labase = 0;
  133. }
  134.  
  135. /* Get the next symbol from the input stream; put it into lookahead buffer;
  136.  * fill token_type[] fast reference cache also.  NLA is the next place where
  137.  * a lookahead ANTLRTokenBase should go.
  138.  */
  139. void ANTLRParser::
  140. consume()
  141. {
  142.     NLA = ((ANTLRTokenBase *)inputTokens->getToken())->getType();
  143.     dirty--;
  144.     lap = (lap+1)&(LLk-1);
  145. }
  146.  
  147. ANTLRTokenBase *ANTLRParser::
  148. LT(int i)
  149. {
  150. #ifdef DEBUG_TOKENBUFFER
  151.     if ( i >= inputTokens->bufferSize() || inputTokens->minTokens() <= LLk )
  152.     {
  153.         static char buf[2000];
  154.         sprintf(buf, "The minimum number of tokens you requested that the\nANTLRTokenBuffer buffer is not enough to satisfy your\nLT(%d) request; increase 'k' argument to constructor for ANTLRTokenBuffer\n", i);
  155.         panic(buf);
  156.     }
  157. #endif
  158.     return (ANTLRTokenBase *) inputTokens->bufferedToken(i-LLk);
  159. }
  160.  
  161. void
  162. ANTLRParser::
  163. look(int k)
  164. {
  165.     int i, c = k - (LLk-dirty);
  166.     for (i=1; i<=c; i++) consume();
  167. }
  168.  
  169. /* fill the lookahead buffer up with k symbols (even if DEMAND_LOOK);
  170.  */
  171. void
  172. ANTLRParser::
  173. prime_lookahead()
  174. {
  175.     int i;
  176.     for(i=1;i<=LLk; i++) consume();
  177.     dirty=0;
  178.     lap = 0;
  179.     labase = 0;
  180. }
  181.  
  182. /* check to see if the current input symbol matches '_t'.
  183.  * During NON demand lookahead mode, dirty will always be 0 and
  184.  * hence the extra code for consuming tokens in _match is never
  185.  * executed; the same routine can be used for both modes.
  186.  */
  187. int ANTLRParser::
  188. _match(TokenType _t, ANTLRChar **MissText,
  189.        TokenType *MissTok, ANTLRLightweightToken **BadTok,
  190.        SetWordType **MissSet)
  191. {
  192.     if ( dirty==LLk ) {
  193.         consume();
  194.     }
  195.     if ( LA(1)!=_t ) {
  196.         *MissText=NULL;
  197.         *MissTok= _t; *BadTok = LT(1);
  198.         *MissSet=NULL;
  199.         return 0;
  200.     }
  201.     dirty++;
  202.     labase = (labase+1)&(LLk-1);    // labase maintained even if !demand look
  203.     return 1;
  204. }
  205.  
  206. /* check to see if the current input symbol matches '_t'.
  207.  * Used during exception handling.
  208.  */
  209. int ANTLRParser::
  210. _match_wsig(TokenType _t)
  211. {
  212.     if ( dirty==LLk ) {
  213.         consume();
  214.     }
  215.     if ( LA(1)!=_t ) return 0;
  216.     dirty++;
  217.     labase = (labase+1)&(LLk-1);    // labase maintained even if !demand look
  218.     return 1;
  219. }
  220.  
  221. /* check to see if the current input symbol matches any token in a set.
  222.  * During NON demand lookahead mode, dirty will always be 0 and
  223.  * hence the extra code for consuming tokens in _match is never
  224.  * executed; the same routine can be used for both modes.
  225.  */
  226. int ANTLRParser::
  227. _setmatch(SetWordType *tset, ANTLRChar **MissText,
  228.        TokenType *MissTok, ANTLRLightweightToken **BadTok,
  229.        SetWordType **MissSet)
  230. {
  231.     if ( dirty==LLk ) {
  232.         consume();
  233.     }
  234.     if ( !set_el(LA(1), tset) ) {
  235.         *MissText=NULL;
  236.         *MissTok= (TokenType)0; *BadTok=LT(1);
  237.         *MissSet=tset;
  238.         return 0;
  239.     }
  240.     dirty++;
  241.     labase = (labase+1)&(LLk-1);    // labase maintained even if !demand look
  242.     return 1;
  243. }
  244.  
  245. int ANTLRParser::
  246. _setmatch_wsig(SetWordType *tset)
  247. {
  248.     if ( dirty==LLk ) {
  249.         consume();
  250.     }
  251.     if ( !set_el(LA(1), tset) ) return 0;
  252.     dirty++;
  253.     labase = (labase+1)&(LLk-1);    // labase maintained even if !demand look
  254.     return 1;
  255. }
  256.  
  257.                    /* Exception handling routines */
  258.  
  259. void ANTLRParser::
  260. consumeUntil(SetWordType *st)
  261. {
  262.     while ( !set_el(LA(1), st) ) { consume(); }
  263. }
  264.  
  265. void ANTLRParser::
  266. consumeUntilToken(int t)
  267. {
  268.     while ( LA(1)!=t ) { consume(); }
  269. }
  270.  
  271.  
  272.                         /* Old error stuff */
  273.  
  274. void ANTLRParser::
  275. resynch(SetWordType *wd,SetWordType mask)
  276. {
  277.     static int consumed = 1;
  278.  
  279.     /* if you enter here without having consumed a token from last resynch
  280.      * force a token consumption.
  281.      */
  282.     if ( !consumed ) {consume(); consumed=1; return;}
  283.  
  284.     /* if current token is in resynch set, we've got what we wanted */
  285.     if ( wd[LA(1)]&mask || LA(1) == eofToken ) {consumed=0; return;}
  286.     
  287.     /* scan until we find something in the resynch set */
  288.     while ( !(wd[LA(1)]&mask) && LA(1) != eofToken ) {consume();}
  289.     consumed=1;
  290. }
  291.  
  292. /* standard error reporting function that assumes DLG-based scanners;
  293.  * you should redefine in subclass to change it or if you use your
  294.  * own scanner.
  295.  */
  296. void ANTLRParser::
  297. syn(ANTLRTokenBase *tok, ANTLRChar *egroup, SetWordType *eset,
  298.     TokenType etok, int k)
  299. {
  300.     int line;
  301.  
  302.     line = ((ANTLRTokenBase *)LT(1))->line();
  303.  
  304.     fprintf(stderr, "line %d: syntax error at \"%s\"",
  305.                     line, ((ANTLRTokenBase *)LT(1))->getText());
  306.     if ( !etok && !eset ) {fprintf(stderr, "\n"); return;}
  307.     if ( k==1 ) fprintf(stderr, " missing");
  308.     else
  309.     {
  310.         fprintf(stderr, "; \"%s\" not", ((ANTLRTokenBase *)LT(1))->getText());
  311.         if ( set_deg(eset)>1 ) fprintf(stderr, " in");
  312.     }
  313.     if ( set_deg(eset)>0 ) edecode(eset);
  314.     else fprintf(stderr, " %s", token_tbl[etok]);
  315.     if ( strlen(egroup) > 0 ) fprintf(stderr, " in %s", egroup);
  316.     fprintf(stderr, "\n");
  317. }
  318.  
  319. /* is b an element of set p? */
  320. int ANTLRParser::
  321. set_el(TokenType b, SetWordType *p)
  322. {
  323.     return( p[DIVWORD(b)] & bitmask[MODWORD(b)] );
  324. }
  325.  
  326. int ANTLRParser::
  327. set_deg(SetWordType *a)
  328. {
  329.     /* Fast compute degree of a set... the number
  330.        of elements present in the set.  Assumes
  331.        that all word bits are used in the set
  332.     */
  333.     register SetWordType *p = a;
  334.     register SetWordType *endp = &(a[bsetsize]);
  335.     register int degree = 0;
  336.  
  337.     if ( a == NULL ) return 0;
  338.     while ( p < endp )
  339.     {
  340.         register SetWordType t = *p;
  341.         register SetWordType *b = &(bitmask[0]);
  342.         do {
  343.             if (t & *b) ++degree;
  344.         } while (++b < &(bitmask[sizeof(SetWordType)*8]));
  345.         p++;
  346.     }
  347.  
  348.     return(degree);
  349. }
  350.  
  351. void ANTLRParser::
  352. edecode(SetWordType *a)
  353. {
  354.     register SetWordType *p = a;
  355.     register SetWordType *endp = &(p[bsetsize]);
  356.     register unsigned e = 0;
  357.  
  358.     if ( set_deg(a)>1 ) fprintf(stderr, " {");
  359.     do {
  360.         register SetWordType t = *p;
  361.         register SetWordType *b = &(bitmask[0]);
  362.         do {
  363.             if ( t & *b ) fprintf(stderr, " %s", token_tbl[e]);
  364.             e++;
  365.         } while (++b < &(bitmask[sizeof(SetWordType)*8]));
  366.     } while (++p < endp);
  367.     if ( set_deg(a)>1 ) fprintf(stderr, " }");
  368. }
  369.  
  370. /* input looks like:
  371.  *      zzFAIL(k, e1, e2, ...,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk)
  372.  * where the zzMiss stuff is set here to the token that did not match
  373.  * (and which set wasn't it a member of).
  374.  */
  375. void
  376. ANTLRParser::FAIL(int k, ...)
  377. {
  378.     static char text[1000];    // dangerous, but I don't care right now
  379.     static SetWordType *f[20];
  380.     SetWordType **miss_set;
  381.     ANTLRChar **miss_text;
  382.     ANTLRLightweightToken **bad_tok;
  383.     ANTLRChar **bad_text;
  384.     unsigned *err_k;
  385.     int i;
  386.     va_list ap;
  387.  
  388.     va_start(ap, k);
  389.  
  390.     text[0] = '\0';
  391.     if ( k>20 ) panic("FAIL: overflowed buffer");
  392.     for (i=1; i<=k; i++)    /* collect all lookahead sets */
  393.     {
  394.         f[i-1] = va_arg(ap, SetWordType *);
  395.     }
  396.     for (i=1; i<=k; i++)    /* look for offending token */
  397.     {
  398.         if ( i>1 ) strcat(text, " ");
  399.         strcat(text, ((ANTLRTokenBase *)LT(i))->getText());
  400.         if ( !set_el(LA(i), f[i-1]) ) break;
  401.     }
  402.     miss_set = va_arg(ap, SetWordType **);
  403.     miss_text = va_arg(ap, ANTLRChar **);
  404.     bad_tok = va_arg(ap, ANTLRLightweightToken **);
  405.     bad_text = va_arg(ap, ANTLRChar **);
  406.     err_k = va_arg(ap, unsigned *);
  407.     if ( i>k )
  408.     {
  409.         /* bad; lookahead is permutation that cannot be matched,
  410.          * but, the ith token of lookahead is valid at the ith position
  411.          * (The old LL sub 1 (k) versus LL(k) parsing technique)
  412.          */
  413.         *miss_set = NULL;
  414.         *miss_text = ((ANTLRTokenBase *)(LT(1)))->getText();
  415.         *bad_tok = LT(1);
  416.         *bad_text = ((ANTLRTokenBase *)(*bad_tok))->getText();
  417.         *err_k = k;
  418.         return;
  419.     }
  420. /*  fprintf(stderr, "%s not in %dth set\n", zztokens[LA(i)], i);*/
  421.     *miss_set = f[i-1];
  422.     *miss_text = text;
  423.     *bad_tok = LT(i);
  424.     *bad_text = ((ANTLRTokenBase *)(*bad_tok))->getText();
  425.     if ( i==1 ) *err_k = 1;
  426.     else *err_k = k;
  427. }
  428.  
  429. int ANTLRParser::
  430. _match_wdfltsig(TokenType tokenWanted, SetWordType *whatFollows)
  431. {
  432.     if ( dirty==LLk ) consume();
  433.  
  434.     if ( LA(1)!=tokenWanted )
  435.     {
  436.         fprintf(stderr,
  437.                 "line %d: syntax error at \"%s\" missing %s\n",
  438.                 LT(1)->line(),
  439.                 (LA(1)==eofToken)?"<eof>":LT(1)->getText(),
  440.                 token_tbl[tokenWanted]);
  441.         consumeUntil( whatFollows );
  442.         return 0;
  443.     }
  444.     else {
  445.         dirty++;
  446.         labase = (labase+1)&(LLk-1); // labase maintained even if !demand look
  447. /*        if ( !demand_look ) consume(); */
  448.         return 1;
  449.     }
  450. }
  451.  
  452.  
  453. int ANTLRParser::
  454. _setmatch_wdfltsig(SetWordType *tokensWanted,
  455.                     TokenType tokenTypeOfSet,
  456.                     SetWordType *whatFollows)
  457. {
  458.     if ( dirty==LLk ) consume();
  459.     if ( !set_el(LA(1), tokensWanted) )
  460.     {
  461.         fprintf(stderr,
  462.                 "line %d: syntax error at \"%s\" missing %s\n",
  463.                 LT(1)->line(),
  464.                 (LA(1)==eofToken)?"<eof>":LT(1)->getText(),
  465.                 token_tbl[tokenTypeOfSet]);
  466.         consumeUntil( whatFollows );
  467.         return 0;
  468.     }
  469.     else {
  470.         dirty++;
  471.         labase = (labase+1)&(LLk-1); // labase maintained even if !demand look
  472. /*        if ( !demand_look ) consume(); */
  473.         return 1;
  474.     }
  475. }
  476.  
  477. char *ANTLRParser::
  478. eMsgd(char *err,int d)
  479. {
  480.     sprintf(eMsgBuffer, err, d);    // dangerous, but I don't care
  481.     return eMsgBuffer;
  482. }
  483.  
  484. char *ANTLRParser::
  485. eMsg(char *err, char *s)
  486. {
  487.     sprintf(eMsgBuffer, err, s);
  488.     return eMsgBuffer;
  489. }
  490.  
  491. char *ANTLRParser::
  492. eMsg2(char *err,char *s, char *t)
  493. {
  494.     sprintf(eMsgBuffer, err, s, t);
  495.     return eMsgBuffer;
  496. }
  497.  
  498. void ANTLRParser::
  499. panic(char *msg)
  500. {
  501.     fprintf(stderr, "ANTLR panic: %s\n", msg);
  502.     exit(-1);
  503. }
  504.